﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace GameForKids
{
    class BilliardGamePlay : DrawableGameComponent
    {
        // bien dem thoi gian
        public float milisecon = 0;
        // hien thi thoi gian choi
        public string timePlay = "";
        public int moved = 0;

        private SpriteFont font;
        private SpriteFont helpFont;
        private bool canShoot = true;
        // Game Object
        public BilliardBoard GameBoard;
        public BilliardStick GameStick;
        public BilliardHole GameHole;
        public List<BilliardBall> GameBalls;
        TouchCollection Touchs;
        public Rectangle TouchRound = new Rectangle(115, 58, 570, 362);

        SoundEffect soundHit;
        SoundEffect soundHitTable;
        SoundEffect soundFall;
        SoundEffect soundShoot;

        public int Level = 1;

        // cong thuc tinh diem
        public static string CongThucGoc = "10-(N-L)";
        public static string CongThucHienTai = "";

        // tao co so du lieu
        private string strConnectionString = @"isostore:/BilliardGameDB.sdf";

        private void ResetBall(int _level)
        {
            bool done = true;
            while (done)
            {
                done = false;
                for (int i = 0; i < _level; i++)
                {
                    BilliardBall ball = new BilliardBall(new Vector2(Suport.Random.Next(150, 650), Suport.Random.Next(100, 380)), 20);
                    ball.BallLink = "BilliardGame/Images/Ball" + i;
                    GameBalls.Add(ball);
                }
                GameHole = new BilliardHole(new Vector2(Suport.Random.Next(200, 600), Suport.Random.Next(145, 340)), 25);

                for (int i = 0; i < GameBalls.Count - 1; i++)
                {
                    if (GameHole.IsCollageWith(GameBalls[i].Position, GameBalls[i].Range) == true)
                    {
                        done = true;
                    }
                    int j = GameBalls.Count - 1;
                    for (; j > i; j--)
                    {
                        if (GameBalls[i].IsHitWith(GameBalls[j].Position, GameBalls[j].Range) == true)
                        {
                            done = true;
                        }
                    }
                }
            }
        }

        public void Reset(int _level)
        {
            Level = _level;

            ChartScreen.listDataScore = this.getListDataScore(GameForKids.userName, Level);
            ChartScreen.levelOfGame = Level;

            Touchs = new TouchCollection();
            GameBoard = new BilliardBoard();
            GameStick = new BilliardStick(30);
            GameStick.BallWidth = 20;
            GameBalls = new List<BilliardBall>();

            ResetBall(_level);
            
        }

        public BilliardGamePlay(Game game)
            : base(game)
        {
            font = this.Game.Content.Load<SpriteFont>("Fonts/ChartFont");
            helpFont = this.Game.Content.Load<SpriteFont>("Fonts/HelpFont");

            soundHit = this.Game.Content.Load<SoundEffect>("BilliardGame/Sounds/Hit");
            soundFall = this.Game.Content.Load<SoundEffect>("BilliardGame/Sounds/Fall");
            soundHitTable = this.Game.Content.Load<SoundEffect>("BilliardGame/Sounds/HitTable");
            soundShoot = this.Game.Content.Load<SoundEffect>("BilliardGame/Sounds/Shoot");

            // tao csdl
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                if (readAndWriteDB.DatabaseExists() == false)
                {
                    readAndWriteDB.CreateDatabase();
                }
            }
            // lay cong thuc
            using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolatedStorageFile.FileExists("CongThuc" + GameForKids.gameState.ToString() + ".txt"))
                {
                    using (IsolatedStorageFileStream isfs = isolatedStorageFile.OpenFile("CongThuc" + GameForKids.gameState.ToString() + ".txt", FileMode.Open))
                    {
                        using (StreamReader reader = new StreamReader(isfs))
                        {
                            while (!reader.EndOfStream)
                            {
                                CongThucHienTai = reader.ReadLine();
                            }
                        }
                    }
                }
            }
            if (CongThucHienTai == "" || CongThucHienTai == null)
                CongThucHienTai = CongThucGoc;
            Reset(1);
        }
     
        // luu theo dang ID - ten  - level - diem - ngay
        public void saveScore(int _score)
        {
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                DataScore newscore = new DataScore {
                    ID = DateTime.Now.ToString(),
                    name = GameForKids.userName, 
                    level = BilliardGame.level,
                    score = _score,
                    day = DateTime.Today.ToShortDateString() };
                readAndWriteDB.TableScore.InsertOnSubmit(newscore);
                readAndWriteDB.SubmitChanges();
            }
        }

        private IList<DataScore> getListDataScore(string _name, int _level)
        {
            IList<DataScore> listDataScore = null;
            using (ReadAndWrite readAndWrite = new ReadAndWrite(strConnectionString))
            {
                try
                {
                    IQueryable<DataScore> dataScoreQuery = from data in readAndWrite.TableScore where data.name.Equals(_name) && data.level == _level select data;
                    listDataScore = dataScoreQuery.ToList();
                }
                catch 
                {
                    
                }
            }
            return listDataScore;
        }

        public void startNewLevel(int _level)
        {
            Reset(_level);
            moved = 0;
            milisecon = 0;
        }

        //tinh diem
        public int getScore()
        {
            int mark = 0;
            XuLyCongThuc xulycongthuc;
            string s = "";

            xulycongthuc = new XuLyCongThuc();
            s = xulycongthuc.TinhDiem(CongThucHienTai, moved, (int)(milisecon / 1000), BilliardGame.level);
            double d = double.Parse(s);
            mark = (int)d;

            if (mark >= 10)
                return 10;
            if (mark <= 0)
                mark = 0;
            return mark;
        }

        // neu tat ca cac cell deu a^n thi Win
        public bool checkComplete()
        {
            if (GameBalls.Count == 0)
                return true;
            else
                return false;
        }


        public override void Initialize()
        {
            base.Initialize();
        }

        public void setTimePlay()
        {
            timePlay = ((int)milisecon / 60000).ToString() + " : " + (((int)milisecon / 1000) % 60).ToString();
        }

        public override void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds;
            milisecon += elapsed;
            setTimePlay();  

            Touchs = TouchPanel.GetState();

            foreach (BilliardBall ball in GameBalls)
            {
                if(TouchRound.Intersects(new Rectangle((int)(ball.Position.X - ball.Range), (int)(ball.Position.Y - ball.Range), (int)(ball.Range*2), (int)(ball.Range*2))) == false)
                {
                    if (ball.Position.X - ball.Range - ball.Range / 2 < TouchRound.X)
                    {
                        ball.Position.X = TouchRound.X + ball.Range - 1;
                    }

                    if (ball.Position.X + ball.Range + ball.Range / 2 > TouchRound.X + TouchRound.Width)
                    {
                        ball.Position.X = TouchRound.X + TouchRound.Width - ball.Range + 1;
                    }

                    if (ball.Position.Y - ball.Range - ball.Range / 2 < TouchRound.Y)
                    {
                        ball.Position.Y = TouchRound.Y + ball.Range - 1;
                    }

                    if (ball.Position.Y + ball.Range + ball.Range / 2 > TouchRound.Y + TouchRound.Height)
                    {
                        ball.Position.Y = TouchRound.Y + TouchRound.Height - ball.Range + 1;
                    }
                }
                foreach (PongLine line in GameBoard.PongLines)
                {
                    if (line.CheckCut(ball.Position, ball.Range) == true)
                    {
                        if (line.IsFence == true)
                        {
                            if (GameForKids.ISMUSIC)
                            {
                                soundHitTable.Play();
                            }
                            if (ball.Position.X - ball.Range - ball.Range / 2 < TouchRound.X)
                            {
                                ball.Position.X = TouchRound.X + ball.Range - 1;
                            }

                            if (ball.Position.X + ball.Range + ball.Range / 2 > TouchRound.X + TouchRound.Width)
                            {
                                ball.Position.X = TouchRound.X + TouchRound.Width - ball.Range + 1;
                            }

                            if (ball.Position.Y - ball.Range - ball.Range / 2 < TouchRound.Y)
                            {
                                ball.Position.Y = TouchRound.Y + ball.Range - 1;
                            }

                            if (ball.Position.Y + ball.Range + ball.Range / 2 > TouchRound.Y + TouchRound.Height)
                            {
                                ball.Position.Y = TouchRound.Y + TouchRound.Height - ball.Range + 1;
                            }
                            int dir = line.HitSide(ball.Position, ball.Range);
                            switch (dir)
                            {
                                case 1:
                                    ball.Velocity.X *= -1;
                                    break;
                                case 2:
                                    ball.Velocity.Y *= -1;
                                    break;
                                case 3:
                                    ball.Velocity.X *= -1;
                                    break;
                                case 4:
                                    ball.Velocity.Y *= -1;
                                    break;
                            }

                        }
                    }
                }
            }

            

            if (canShoot == true)
            {
                if (GameStick.OnHit == false)
                {
                    //kiem tra xem van con touch
                    if (GameStick.OnTouch == true)
                    {
                        bool done = false;
                        foreach (TouchLocation touch in Touchs)
                        {
                            if (touch.Id == GameStick.TouchId)
                            {
                                // neu da re rang ngoai vung bong thi bat dau ve
                                if (GameStick.TargetBall.CheckTouch(touch.Position) == false)
                                {
                                    GameStick.OnRepaire = true;
                                }
                                else
                                {
                                    GameStick.OnRepaire = false;
                                }

                                GameStick.MovePosition = touch.Position;

                                done = true;
                            }
                        }
                        if (done == false)
                        {
                            if (GameStick.OnRepaire == true)
                            {
                                GameStick.OnHit = true;
                                GameStick.IsTranfer = true;
                            }
                            GameStick.OnTouch = false;
                            GameStick.OnRepaire = false;
                        }
                    }
                    else// gan lai touch neu chua co
                    {
                        bool isBreak = false;
                        foreach (BilliardBall ball in GameBalls)
                        {
                            if (ball.BallLink == "BilliardGame/Images/Ball0")
                            {
                                foreach (TouchLocation touch in Touchs)
                                {
                                    if (ball.CheckTouch(touch.Position) == true)
                                    {
                                        GameStick.OnTouch = true;
                                        GameStick.TouchId = touch.Id;
                                        GameStick.MovePosition = touch.Position;
                                        GameStick.TargetBall = ball;
                                        GameStick.CenterBall = ball.Position;
                                        isBreak = true;
                                        break;
                                    }
                                }
                            }
                            if (isBreak == true)
                            {
                                break;
                            }
                        }
                    }

                    // cap nhat vi tri va cac tham so neu
                    if (GameStick.OnTouch == true)
                    {
                        if (GameStick.OnRepaire == true)
                        {
                            GameStick.RootPosition = GameStick.RootTemp = GameStick.GetCutPoint(GameStick.CenterBall, 20, GameStick.MovePosition);
                            GameStick.Rotation = (float)Math.Atan2((GameStick.MovePosition - GameStick.RootPosition).Y, (GameStick.MovePosition - GameStick.RootPosition).X);
                            Vector2 delta = GameStick.GetTheDelta(GameStick.RootTemp, GameStick.MovePosition);
                            if ((GameStick.MovePosition - GameStick.RootTemp).Length() > GameStick.MaxStrenght.Length())
                            {
                                delta = delta / delta.Length();
                                delta *= GameStick.MaxStrenght;
                            }
                            GameStick.Strenght = delta;
                            GameStick.RootPosition += GameStick.GetTheDelta(GameStick.CenterBall, GameStick.MovePosition);
                        }
                    }
                }
                    // short
                else
                {
                    if (GameStick.IsTranfer == true)
                    {
                        if (GameForKids.ISMUSIC)
                        {
                            soundShoot.Play();
                        }
                        moved++;
                        GameStick.TargetBall.Velocity = GameStick.Strenght * (-2.0f);
                        GameStick.IsTranfer = false;
                    }
                }
            }

            if (GameStick.Strenght.Length() < 1.0f)
            {
                GameStick.OnHit = false;
            }

            canShoot = true;
            GameStick.Update(gameTime);

            int removeIndex = -1;
            for (int i = 0; i < GameBalls.Count; i++ )
            {
                GameBalls[i].Update(gameTime);
                if (GameBalls[i].Velocity != Vector2.Zero)
                {
                    canShoot = false;
                }
                if (GameHole.IsCollageWith(GameBalls[i].Position, GameBalls[i].Range) == true)
                {
                    removeIndex = i;
                }
            }
            if (removeIndex != -1)
            {
                if (removeIndex == 0)
                {
                    if (GameBalls.Count == 1)
                    {
                        GameBalls.RemoveAt(removeIndex);
                        if (GameForKids.ISMUSIC)
                        {
                            soundFall.Play();
                        }
                    }
                }
                else
                {
                    GameBalls.RemoveAt(removeIndex);
                    if (GameForKids.ISMUSIC)
                    {
                        soundFall.Play();
                    }
                }
            }

            Vector2 velocity_i = new Vector2();
            Vector2 velocyty_j = new Vector2();

            for(int i = 0; i < GameBalls.Count - 1; i++)
            {
                int j = GameBalls.Count - 1;
                for (; j > i;j-- )
                {
                    // kiem tra va cham
                    if(GameBalls[i].IsHitWith(GameBalls[j].Position, GameBalls[j].Range) == true)
                    {
                        if (GameForKids.ISMUSIC)
                        {
                            soundHit.Play();
                        }
                        velocity_i = Vector2.Zero;
                        velocyty_j = Vector2.Zero;
                        if (GameBalls[i].Velocity != Vector2.Zero)
                        {
                            Vector2 temp = GameBalls[i].HitDangeUnit(GameBalls[j].Position);
                            float angle = (float)(Math.Atan2(GameBalls[i].Velocity.Y, GameBalls[i].Velocity.X) - Math.Atan2(temp.Y, temp.X));
                            while (angle > Math.PI / 4.0f)
                            {
                                angle -= (float)Math.PI / 4.0f;
                            }
                            while (angle < -Math.PI / 4.0f)
                            {
                                angle += (float)Math.PI / 4.0f;
                            }
                            temp *= (float)(Math.Abs(angle) / (Math.PI / 4.0f)) * GameBalls[i].Velocity.Length();
                            Vector2 temp2 = GameBalls[i].Velocity - temp;
                            velocity_i = temp2;
                            velocyty_j = temp;
                        }

                        if (GameBalls[j].Velocity != Vector2.Zero)
                        {
                            Vector2 temp = GameBalls[j].HitDangeUnit(GameBalls[i].Position);
                            float angle = (float)(Math.Atan2(GameBalls[j].Velocity.Y, GameBalls[j].Velocity.X) - Math.Atan2(temp.Y, temp.X));
                            while (angle > Math.PI / 4.0f)
                            {
                                angle -= (float)Math.PI / 4.0f;
                            }
                            while (angle < -Math.PI / 4.0f)
                            {
                                angle += (float)Math.PI / 4.0f;
                            }
                            temp *= (float)(Math.Abs(angle) / (Math.PI / 4.0f)) * GameBalls[j].Velocity.Length();
                            Vector2 temp2 = GameBalls[j].Velocity - temp;
                            velocity_i += temp;
                            velocyty_j += temp2;
                        }

                        GameBalls[i].Velocity = velocity_i;
                        GameBalls[j].Velocity = velocyty_j;
                    }
                }
            }

            base.Update(gameTime);
        }

        public virtual void Draw(GameTime gametime, SpriteBatch spriteBatch)
        {
            GameBoard.Draw(spriteBatch);
            GameHole.Draw(spriteBatch);
            foreach (BilliardBall ball in GameBalls)
            {
                ball.Draw(spriteBatch);
            }
            GameStick.Draw(spriteBatch);
            spriteBatch.DrawString(helpFont, timePlay, new Vector2(10, 250), Color.White);
            spriteBatch.DrawString(helpFont, moved.ToString(), new Vector2(740, 250), Color.White);
        
          }

        public void TouchEvent(TouchLocation touch)
        {
            
        }
    }
}
